﻿#pragma once

#ifndef ZZJ_MENU_HPP
#define ZZJ_MENU_HPP

#include <cstdint>
#include <cstdlib>
#include <print>
#include <chrono>
#include <iostream>
#include <ranges>
#include <mutex>
#include <memory>
#include <format>
#include <ctime>
#include <iomanip>

#include "zzj.col.hpp"
#include <string>
#include <corecrt.h>

namespace zzj
{
	inline namespace menu
	{
	}
}

namespace menu
{
	using namespace col;
	using namespace col::literals;
	using namespace std::literals;

	using MessageType =
	enum class MsgTy : std::int_fast8_t
	{
		NORMAL = 0,
		MESSAGE,
		SUCCESS,
		NOTE,
		WARNING,
		ERROR
	};

	/* 界面类 */
	class Menu
	{
	private:
		using TimePoint = std::chrono::high_resolution_clock::time_point;
	public:
		struct StatFlag
		{
			bool is_ready{false};
			bool is_fresh{false};
			bool is_wait{false};
			bool is_readFile{false};
			bool is_writeFile{false};
			bool is_prnMsg{false};
		} statFlag;
	private:
		std::string m_systemName{"系统"};
		std::string m_userName{"user"};

		int m_optionId{1};
		int m_option{1};


		TimePoint m_startTime{std::chrono::high_resolution_clock::now()};
		TimePoint m_latestTime{m_startTime};
	public:
		Menu() = default;

		explicit(false) Menu(std::string_view const sys_name)
			: m_systemName{sys_name}
		{
		}

		explicit(false) Menu(std::string_view const sys_name, std::string_view const usr_name)
			: m_systemName{sys_name}, m_userName{usr_name}
		{
		}

		Menu(Menu&&) = default;
		~Menu() = default;
		Menu(Menu const&) = default;
		Menu& operator=(Menu const&) = default;
		Menu& operator=(Menu&&) = default;

		void printMsg(MsgTy const ty, std::string_view msg);

		void statusBar();
		void statusBarFr();
		void fresh();
		void waitEnterMsg();
		void options();
		void ready();
	};


	/*****************************************************************
	 *
	 *		MENU 定义
	 *
	 *****************************************************************/

	inline void Menu::printMsg(MsgTy const ty, std::string_view msg)
	{
		statFlag.is_prnMsg = true;

		std::string tyMsg;
		auto col = Color(ColorName::DEFAULT);
		switch (ty) {
		case MsgTy::MESSAGE:
			col.set(CName::BLUE);
			tyMsg = "MSG";
			break;
		case MessageType::SUCCESS:
			col.set(CName::GREEN);
			tyMsg = "SUCCESS";
			break;
		case MsgTy::NOTE:
			col.set(CName::YELLOW);
			tyMsg = "NOTE";
			break;
		case MsgTy::WARNING:
			col.set(CName::YELLOW);
			tyMsg = "WARNING";
			break;
		case MsgTy::ERROR:
			col.set(CName::RED);
			tyMsg = "ERROR";
			break;
		case MsgTy::NORMAL:
			col.set(CName::CYAN);
			tyMsg = "NORMAL";
			break;
		default:
			tyMsg = "NULL";
			col.set(ColorName::DEFAULT);
		}
		col.print();
		std::println("[{}][{}]:「{}」", ">", tyMsg, msg);
	}


	inline void Menu::statusBar()
	{
		auto const latestTime = std::chrono::high_resolution_clock::now();
		auto const dur = latestTime - m_latestTime;

		m_latestTime = latestTime;


		auto col = Color(ColorName::CYAN);

		std::print("[{1:}][{0:}]", m_userName, m_systemName);
		col.setPrn(ColorName::GREEN);


		if constexpr (true) {
			std::println("[{:%Y-%m-%d %H:%M}][{}{}s]",
			             std::chrono::system_clock::now(),
			             "Times：", std::chrono::duration_cast<std::chrono::seconds>(dur).count());
		}
		else {
			char timeStr[80]{};
			auto const now = std::chrono::system_clock::now();
			std::time_t const now_c = std::chrono::system_clock::to_time_t(now);
			std::tm now_tm{};
			if (auto err = localtime_s(&now_tm, &now_c);
				err == 0) {
				
			}
			if (auto err = std::strftime(timeStr, sizeof(timeStr), "%Y-%m-%d %H:%M:%S", &now_tm);
				err == 0) {
				
			}
			std::println("[{}][{}{}s]",
			             timeStr, "Times：",
			             std::chrono::duration_cast<std::chrono::seconds>(dur).count());
		}

		col.setPrn(ColorName::MAGENTA);
		if (statFlag.is_readFile) {
			std::print("[文件读取成功]");
		}
		else {
			std::print("[未读取文件]");
		}
		if (statFlag.is_writeFile) {
			std::print("[文件写入成功]");
		}
		else {
			std::print("[未写入文件]");
		}
		col.setPrn(ColorName::RED);
		std::println("[End]\n");

		statFlag.is_fresh = false;
	}

	inline void Menu::statusBarFr()
	{
		if (!statFlag.is_fresh) {
			Menu::fresh();
			this->statusBar();
		}
		statFlag.is_fresh = false;
	}

	inline void Menu::fresh()
	{
		static std::mutex mtx;
		{
			std::scoped_lock<std::mutex> lock(mtx);
			if constexpr (sys_info.is_windows) {
				std::system("cls");
			}
			else {
				std::system("clear");
			}
			statFlag.is_fresh = true;
		}
	}


	inline void Menu::waitEnterMsg()
	{
		auto const markedWords{"按下回车键以继续"s};

		statFlag.is_wait = true;
		{
			auto col = Color{ColorName::YELLOW};
			this->printMsg(MessageType::NOTE, markedWords);
			std::cin.clear();
			if (std::cin.rdbuf()->in_avail() > 0) {
				std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
			}
			std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
		}
		statFlag.is_wait = false;
	}

	inline void Menu::options()
	{
		statFlag.is_fresh = false;

		std::vector<int> vv;

		for (auto val : std::ranges::istream_view<int>(std::cin)
		     | std::views::take_while([](const auto& v) { return v < 5; })
		     | std::views::transform([](const auto& v) { return v * 2; })) {
			std::println("> {}", val);
			vv.push_back(val);
		}
		std::println("end input");
	}

	inline void Menu::ready()
	{
		statFlag.is_ready = true;
		this->printMsg(MessageType::MESSAGE, "系统就绪！");
	}
}

#endif
